home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / libsrc~1.z / libsrc~1 / fixnum.s < prev    next >
Encoding:
Text File  |  1989-12-28  |  5.6 KB  |  256 lines

  1. #APP
  2. #
  3. |
  4. | Subroutines needed by GNU C for long integer arithmetic.
  5. |
  6. | Revision 1.4, jrb 09-06-89
  7. | More bug fixes, fixed mod routines to push args correctly
  8. |
  9. | Revision 1.3, jrb 08-15-89
  10. | Merged in kai-uwe's stuff (thanks!). minor cleanup, some hacks and
  11. | bug fixes. Dont run this thru cpp anymore.
  12. |
  13. | Revision 1.2, kub 05-23-89
  14. | Modified by Kai-Uwe Bloem (I5110401@DBSTU1.BITNET for now) to get some
  15. | speed out of this. Completely rewrote the modulo stuff.
  16. |
  17. | Revision 1.1, kub
  18. | initial revision from jrd
  19.  
  20. |
  21. | _umulsi3 (a, b)
  22. |      unsigned long a, b;
  23. | {
  24. |   return a * b;
  25. | }
  26. |
  27.     .text
  28.     .even
  29.     .globl ___umulsi3
  30.     .globl __umulsi3
  31. ___umulsi3:
  32. __umulsi3:
  33.     movel d2,a1        | save d2
  34.  
  35.     moveq #0,d0        | prepare result
  36.     movew a7@(10),d1    | get lo part of b
  37.     beq umul_1        | zero, no multiplies
  38.     movew a7@(4),d2        | get hi part of a
  39.     beq umul_0        | zero, skip this
  40.     mulu d1,d2        | mul a hi by b lo
  41.     swap d2            | shift over
  42.     clrw d2            |  ...by 16
  43.     movel d2,d0        | save that
  44. umul_0:
  45.     movew a7@(6),d2        | get lo part of a
  46.     beq umul_ret        | zero, no multiplies
  47.     mulu d2,d1        | mul a lo by b lo
  48.     addl d1,d0        | add that in
  49. umul_1:
  50.     movew a7@(8),d1        | get b hi
  51.     beq umul_ret
  52.     movew a7@(6),d2        | and a lo
  53.     beq umul_ret
  54.     mulu d1,d2        | mult those
  55.     swap d2            | shift over
  56.     clrw d2            |  ...by 16
  57.     addl d2,d0        | and add that in
  58. umul_ret:
  59.     movel a1,d2        | get d2 back
  60.  
  61.     rts
  62. |
  63. | _mulsi3 (a, b)
  64. |      long a, b;
  65. | {
  66. |   return a * b;
  67. | }
  68. |
  69.     .text
  70.     .even
  71.     .globl ___mulsi3
  72.     .globl __mulsi3
  73. ___mulsi3:
  74. __mulsi3:
  75.     link a6,#-2        | one word of local
  76.     clrw a6@(-2)        | zap the local; it's our neg flg
  77.  
  78.     movel a6@(12),d0    | get b
  79.     bpl muls1        | pos, ok
  80.     negl d0            | negate it
  81.     addqw #1,a6@(-2)    | and inc the flag
  82. muls1:
  83.     movel d0,sp@-        | push adjusted b
  84.     movel a6@(8),d0        | get a
  85.     bpl muls2        | pos, ok
  86.     negl d0            | negate it
  87.     subqw #1,a6@(-2)    | and dec the flag
  88. muls2:
  89.     movel d0,sp@-        | push adjusted a
  90.     jbsr ___umulsi3        | do an unsigned mult
  91.     addql #8,sp        | flush args
  92.     tstw a6@(-2)        | flag set?
  93.     beq muls3        | nope, go ahead and return
  94.     negl d0            | negate the result
  95. muls3:
  96.     unlk a6            | unlink the frame
  97.     rts            | done
  98. |
  99. | _udivsi3 (a, b)
  100. |      unsigned long a, b;
  101. | {
  102. |   return a / b in d0
  103. |   return a % b in d1
  104. | }
  105. |
  106.     .text
  107.     .even
  108.     .globl ___udivsi3
  109.     .globl __udivsi3
  110. ___udivsi3:
  111. __udivsi3:
  112.     movel d2,a0        | save the work area
  113.     movel d3,a1
  114.  
  115.     moveq #0,d0        | d0 will be accum
  116.     movel a7@(8),d2        | d2 is b, divisor
  117.     beq udiv_err        | b = 0 => error
  118.     movel a7@(4),d1        | d1 is a, dividend
  119.     beq udiv_done        | a = 0 => result 0
  120.     cmpl d2,d1        | b > a => result 0
  121.     bcs udiv_done
  122.     moveq #31,d0        | d0 is bit num for testing need to sub
  123.     tstb a7@(4)        | find byte with highest bit of dividend
  124.     bne udiv_bit
  125.     subql #8,d0
  126.     tstb a7@(5)
  127.     bne udiv_bit
  128.     subql #8,d0
  129.     tstb a7@(6)
  130.     bne udiv_bit
  131.     subql #8,d0
  132. udiv_bit:
  133.     btst d0,d1        | byte found, now find bit
  134.     dbne d0,udiv_bit
  135.     moveql #1,d3        | get 1 into bit 0 of bit mask
  136.     | d0 now contains the number of the highest 1-bit set in the dividend.
  137.     | Now shift the divisor left to move a 1-bit at this position.
  138.     | Possible because divisor (in d2) <= dividend (in d1)!
  139. udiv_sl:
  140.     btst d0,d2        | bit get aligned to highest bit of a yet?
  141.     bne udiv_start        | yes, start testing for subtraction
  142.     addl d3,d3        | shift bitmask left
  143.     addl d2,d2        | shift divisor left
  144.     bra udiv_sl
  145. udiv_start:
  146.     | valid condition now : d2 <= d1 <= 2*d2
  147.     | Now apply the same algorithm as used to divide manually :
  148.     | subtract and shift right....
  149.     moveq #0,d0        | prepare accumulator
  150. udiv_sr:
  151.     cmpl d2,d1        | divisor > dividend?
  152.     bcs udiv_s
  153.     orl d3,d0        | set this bit in d0
  154.     subl d2,d1        | take divisor (shifted) out of dividend
  155.     beq udiv_done        | nothing left to do
  156. udiv_s:
  157.     lsrl #1,d2        | shift right one
  158.     lsrl #1,d3        | and the bitnum too
  159.     bne udiv_sr        | more bits, keep dividing
  160.  
  161. udiv_done:
  162.     | d0 = divisor DIV dividend, d1 = divisor MOD dividend. Think of it !
  163.     | This makes implementation of % fast and easy, see below !
  164.     movel a0,d2        | get work regs back
  165.     movel a1,d3
  166.     rts
  167. udiv_err:
  168.     divs d2,d1        | cause division trap
  169.     bra udiv_done        | back to user after exception handling
  170. |
  171. | _divsi3 (a, b)
  172. |      long a, b;
  173. | {
  174. |   return a / b in d0
  175. |   return a % b in d1
  176. | }
  177. |
  178.     .text
  179.     .even
  180.     .globl ___divsi3
  181.     .globl __divsi3
  182. ___divsi3:
  183. __divsi3:
  184.     link a6,#-2        | 2 bytes of local
  185.     clrw a6@(-2)        | zap the local; it's our neg flg
  186.  
  187.     movel a6@(12),d0    | get b
  188.     bge divs1        | pos, ok
  189.     negl d0            | negate it
  190.     addqw #1,a6@(-2)    | and inc the flag
  191. divs1:
  192.     movel d0,sp@-        | push adjusted b
  193.     movel a6@(8),d0        | get a
  194.     bge divs2        | pos, ok
  195.     negl d0            | negate it
  196.     subqw #1,a6@(-2)    | and dec the flag
  197. divs2:
  198.     movel d0,sp@-        | push adjusted a
  199.     jbsr __udivsi3        | do an unsigned div
  200.     addql #8,sp        | flush args
  201.     tstw a6@(-2)        | flag set?
  202.     beq divs3        | nope, go ahead and return
  203.     negl d0            | negate the result
  204. divs3:
  205.     tstb a6@(8)
  206.     bpl divs4
  207.     negl d1            | correct the remainder
  208.     | The next line would be applied if a modulus as defined in algebra
  209.     | is required (well, i think so).
  210.     | In computer science % is mostly defined as a % b = a - (a/b)*b, so...
  211. |    addl a6@(8),d1
  212. divs4:
  213.     unlk a6            | unlink the frame
  214.     rts            | done!
  215. |
  216. | _umodsi3 (a, b)
  217. |      unsigned long a, b;
  218. | {
  219. |   return a % b;
  220. | }
  221. |
  222.     .text
  223.     .even
  224.     .globl ___umodsi3
  225.     .globl __umodsi3
  226. ___umodsi3:
  227. __umodsi3:
  228.     movel sp@(8),sp@-    |  push b
  229.     movel sp@(8),sp@-    |  push a sp has been dec by 4 by previous push
  230.     jbsr __udivsi3
  231.     movel d1,d0        | The div operation just delivers the remainder
  232.     addql #8,sp
  233.     rts
  234. |
  235. | _modsi3 (a, b)
  236. |      long a, b;
  237. | {
  238. |   return a % b;
  239. | }
  240. |
  241.     .text
  242.     .even
  243.     .globl ___modsi3
  244.     .globl __modsi3
  245. ___modsi3:
  246. __modsi3:
  247.     movel sp@(8),sp@-    | push b
  248.     movel sp@(8),sp@-    | push a    sp dec. by 4 by previous push
  249.     jbsr __divsi3
  250.     movel d1,d0        | The div operation just delivers the remainder
  251.     addql #8,sp
  252.     rts
  253. | eof
  254. |
  255.